#ifndef INTEGRATION_METHOD_H
#define INTEGRATION_METHOD_H
#include <vector>
#include <iostream>
//#include "vector.h"
#include "matrix.h"
#include "state.h"
#include "particle.h"
#include "spring.h"

#define DEFAULT 0
#define KANG2000 1
#define ZHOU2005 2
#define EBERHARDT2000 3
#define KANG2004 4


//typedef std::vector<State> StateList;
class IntegrationMethod
{
    public:
        IntegrationMethod();

        IntegrationMethod(double, double, std::vector<State>, std::vector< std::vector<Particle *> > &, std::vector< std::vector<Spring *> > &, bool, int, double, double, double, Vector3D);

        virtual void calculate(bool, unsigned int, double) = 0;


        double getDeltaT() const; //time step

        void setDeltaT(double _dt) {deltaT = _dt;};


        double getGravity() const; //gravity

        void setGravity(double _g) {gravity = _g;};

        void restart();


        void setActiveAir(bool _b) {useAir = _b;}
        void setAirType(unsigned int _type) {airType = _type;}
        void setAirPeriod(double _p) {airPeriod = _p;}
        void setAirRepeat(double _r) {airRepeat = _r;}
        void setAirDirection(const Vector3D &_d) {airDirection = _d;}
        void setAirViscosity(double _v) {fluidViscosity = _v;}


        const Vector &getPosition(unsigned int) const; //position vector of current state

        const Vector &getVelocity(unsigned int) const; //velocity vector of current state

        const State &getCurrentState(unsigned int) const; //return the current state of fabric in the position i

        const State &getPreviousState(unsigned int) const; //return the previous state of fabric in the position i

        void setState(unsigned int, const State &); //modifies the previous and current states

        void setCurrentStateInParticle(unsigned int, unsigned int, const Vector3D &, const Vector3D &); //modifies the current state's velocity and position

        void setCurrentStateInParticle(unsigned int, unsigned int, bool, bool, bool, const Vector3D &, const Vector3D &);

        void setCurrentState(unsigned int, const State &); //modifies the current state's velocity and position

    protected:
        double deltaT; //time step

        double currentDeltaT; //time step para usar quando ouver colisão

        double gravity;

        std::vector<State> currentState; //vector of current states

        std::vector<State> previousState; //vector of previous states

        std::vector< std::vector<Particle *> > particles; //vector of vectors of particle

        std::vector< std::vector<Spring *> > springs; //vector of vectors of spring

        bool useAir;
        unsigned int airType;
        double airPeriod;
        double airRepeat;
        Vector3D airDirection;
        double fluidViscosity;
        static bool ocilation;
        static unsigned int ocilationTimes;

        virtual State f(const State &, unsigned int); //calculating the function F

        virtual Vector acceleration(const State &, unsigned int); //calculating the acceleration

        Vector *populateResultantForces(const State &, unsigned int, unsigned int = 0); //calculating the vector resultant force

        Matrix *populateM(const State &, unsigned int); //calculating the mass matrix

        Matrix decompositionCholesky(const Matrix&); //calculating decomposition Cholesky

        Vector3D velocityInTime(double) const; //get the velocity in the time using a sin function
};



#endif // METHODS_H
